package net.monare.mifss.admin.ui.win;

import com.vaadin.ui.*;
import com.vaadin.ui.themes.Runo;
import net.monare.mifss.MifssAdminMainUI;
import net.monare.mifss.MifssMessages;
import net.monare.mifss.configurations.pojo.StorageDef;
import net.monare.mifss.exceptions.StorageServiceException;
import net.monare.mifss.lib.StorageProgressWalker;
import net.monare.mifss.services.StorageService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.*;

@org.springframework.stereotype.Component
@Scope("prototype")
public class ReCreateStorageWindow extends Window {

    private StorageDef storageDef;
    private ProgressBar progressBar;

    private Label currentCountLabel;
    private Label currentCount;

    private Label maxCountLabel;
    private Label maxCount;

    private Label storageIdLabel;
    private Label storageName;

    private RecreateWorker worker;
    private StorageService storageService;

    private TextArea sysOutput;
    private Throwable error;

    final NativeButton startButton;

    @Autowired
    private transient ApplicationContext applicationContext;


    public ReCreateStorageWindow(StorageDef storageDef) {

        this.storageDef = storageDef;

        MifssAdminMainUI ui = (MifssAdminMainUI) UI.getCurrent();
        storageService =  applicationContext.getBean(StorageService.class);


        setCaption(MifssMessages.getMessage("title.recreate.storage"));
        setModal(true);
        setResizable(false);

        setStyleName(Runo.WINDOW_DIALOG);

        setWidth("440");
        setHeight("400");

        VerticalLayout layout = new VerticalLayout();

        layout.setMargin(true);
        layout.setSpacing(true);


        //
        // storage info bar
        storageIdLabel = new Label(MifssMessages.getMessage("label.storage.name") + ":");
        storageIdLabel.setWidth("150px");
        storageName = new Label(storageDef.getName());
        storageName.setWidth("50px");

        HorizontalLayout storageInfoBar = new HorizontalLayout();
        storageInfoBar.setSpacing(true);
        storageInfoBar.addComponent(storageIdLabel);
        storageInfoBar.addComponent(storageName);

        layout.addComponent(storageInfoBar);


        //
        // max count bar
        maxCountLabel = new Label(MifssMessages.getMessage("label.max.records") + ":");
        maxCountLabel.setWidth("150px");
        maxCount = new Label("-");
        maxCount.setWidth("50px");

        HorizontalLayout maxCountBar = new HorizontalLayout();
        maxCountBar.setSpacing(true);
        maxCountBar.addComponent(maxCountLabel);
        maxCountBar.addComponent(maxCount);

        layout.addComponent(maxCountBar);


        //
        // current count bar
        currentCountLabel = new Label(MifssMessages.getMessage("label.processing.current.record") + ":");
        currentCountLabel.setWidth("150px");
        currentCount = new Label("-");
        currentCount.setWidth("50px");

        HorizontalLayout currCountBar = new HorizontalLayout();
        currCountBar.setSpacing(true);
        currCountBar.addComponent(currentCountLabel);
        currCountBar.addComponent(currentCount);

        layout.addComponent(currCountBar);

        //
        // progress indicator
        progressBar = new ProgressBar();
        progressBar.setIndeterminate(false);
        progressBar.setEnabled(false);
        progressBar.setWidth("400px");

        layout.addComponent(progressBar);


        //
        // message box
        sysOutput = new TextArea();
        sysOutput.setWidth("400px");
        sysOutput.setHeight("200px");
        layout.addComponent(sysOutput);

        startButton = new NativeButton("Recreate storage");

        startButton.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {

                worker = new RecreateWorker();
                worker.start();
                progressBar.setEnabled(true);
                progressBar.setValue(0f);
                progressBar.setVisible(true);
                startButton.setEnabled(false);

                addToSysOutput(MifssMessages.getMessage("sys.message.recreate.start"));
                setClosable(false);

            }
        });

        layout.addComponent(startButton);
        layout.setComponentAlignment(startButton, Alignment.MIDDLE_RIGHT);

        setContent(layout);


    }

    public class RecreateWorker extends Thread {

        @Override
        public void run() {


            try {


                storageService.recreateCompleteContentForStorage(storageDef.getName(),new StorageProgressWalker() {

                    @Override
                    public void onProgress( final long recordNum, final long resultSize) {

                        System.out.println(""+recordNum + "-"+resultSize);

                        // Update the UI thread-safely
                        UI.getCurrent().access(new Runnable() {
                            @Override
                            public void run() {
                                progressBar.setValue(new Float((float) (recordNum + 1) / resultSize));
                                maxCount.setValue(Integer.toString((int)resultSize));
                                currentCount.setValue(Integer.toString((int)recordNum));
                            }
                        });
                    }

                    @Override
                    public void setSize(long resultSize) {

                    }
                });

                // recreation is complete enable window
                UI.getCurrent().access(new Runnable() {
                    @Override
                    public void run(){
                        setClosable(true);
                        addToSysOutput(MifssMessages.getMessage("sys.success.recreate"));
                    }
                });


            } catch (StorageServiceException e) {

                error = e;

                UI.getCurrent().access(new Runnable() {
                    @Override
                    public void run(){

                        setClosable(true);

                        addToSysOutput("Storage re-creation failed ...");
                        addToSysOutput(MifssMessages.getMessage("sys.error.recreate"));
                    }
                });

            }


        }
    }

    private void addToSysOutput(String value){


        String oldValue = sysOutput.getValue();

        if(StringUtils.isNotEmpty(oldValue)){
            sysOutput.setValue(oldValue + "\n" + value);
        } else{
            sysOutput.setValue(value);
        }

    }

}
